import os
import shutil
import re

UTF_8 = 'utf-8'
NEW_LINE_LF = '\n'
NEW_LINE_CR_LF = '\r\n'
REG_FILE = re.compile('.+\\..+')


def is_exist(path_) -> bool:
    return os.path.exists(path_)


def is_file(file_path) -> bool:
    return os.path.isfile(file_path)


def is_dir(path_) -> bool:
    return os.path.isdir(path_)


def is_file_exist(file_) -> bool:
    return is_exist(file_) and is_file(file_)


def is_dir_exists(dir_) -> bool:
    return is_exist(dir_) and is_dir(dir_)


def relative_path(base_, relative_) -> str:
    return os.path.join(base_, relative_)


def normalize_path(base_, relative_=None) -> str:
    if relative_ is None:
        return os.path.normpath(base_)
    return os.path.normpath(relative_path(base_, relative_))


def filename_of(path_) -> str:
    return os.path.basename(path_)


def file_must_exist(file_):
    if is_file_exist(file_):
        pass
    else:
        raise FileNotFoundError(f'文件不存在：{file_}')


def file_must_not_exist(file_):
    if is_file_exist(file_):
        raise FileNotFoundError(f'文件已存在：{file_}')


def dir_must_exist(dir_):
    if is_dir_exists(dir_):
        pass
    else:
        raise FileNotFoundError(f'目录不存在: {dir_}')


def dir_must_not_exist(dir_):
    if is_dir_exists(dir_):
        raise FileNotFoundError(f'目录已存在: {dir_}')


def make_dirs(path_):
    if is_dir_exists(path_):
        pass
    else:
        os.makedirs(normalize_path(path_))


def make_zip_archive(basename: str, dir_):
    dir_must_exist(dir_)
    shutil.make_archive(basename, format='zip', root_dir=normalize_path(dir_), base_dir='.')


def two_identical_paths(path1, path2) -> bool:
    return normalize_path(path1) == normalize_path(path2)


def copy_file(from_, to_, overwrite=False):
    file_must_exist(from_)
    if two_identical_paths(from_, to_):
        raise ValueError('复制操作，源文件和目标文件不能是同一个！')
    if overwrite:
        shutil.copyfile(from_, to_)
    elif is_file_exist(to_) or is_dir_exists(to_):
        raise FileExistsError(f'存在同名的文件/目录: {to_}')
    else:
        shutil.copyfile(from_, to_)


def delete_file(file_):
    if is_file_exist(file_):
        os.remove(file_)


def copy_dir(from_, to_, overwrite=False):
    dir_must_exist(from_)
    if two_identical_paths(from_, to_):
        raise ValueError('复制操作，源目录和目标目录不能是同一个！')
    if overwrite:
        shutil.copytree(from_, to_, dirs_exist_ok=True)
    elif is_file_exist(to_) or is_dir_exists(to_):
        raise FileExistsError(f'存在同名的文件/目录: {to_}')
    else:
        shutil.copytree(from_, to_)


def delete_dir(dir_):
    if is_dir_exists(dir_):
        shutil.rmtree(dir_)


def open_utf8_read(file):
    return open(file, 'r', encoding=UTF_8)


def open_utf8_write(file, new_line=NEW_LINE_LF):
    return open(file, 'w', encoding=UTF_8, newline=new_line)


def open_utf8_append(file, new_line=NEW_LINE_LF):
    return open(file, 'a', encoding=UTF_8, newline=new_line)
